/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.                                     
 */
/** 
 * UXInteractionクラス.
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id$<br>
 */
package jp.ize.ux;

import jp.ize.ux.UXFocusManager;

// {{{ enum UXInteractionParameter
/**
 * ユーザーからの操作
 */
enum UXInteractionParameter
{
	Mouse ( m : UXMouseEvent );
	Keyboard ( k : UXKeyboardEvent );
	Forcus ( f : UXFocusEvent );
	Any ( p : Dynamic );
}
// }}}
// {{{ class UXInteraction<S>
/**
 * UXInteractionクラス<br>
 * 反応するユーザーの操作(events)、状態判定(judge)、画面反応(acts)、内部状態の更新(work)を一体化した、
 * ユーザーとの相互作用(Interaction)を抽象化したUX-Frameworkの根幹を成すクラス(の一つ)です。
 * UX-Frameworkでは、UXInteractionによってユーザーとの'相互作用'を具体的なオブジェクトと切り離して記述できます。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id$<br>
 */
class UXInteraction<S>
{
	// {{{ properties

	//プライベート変数
	/**
	 * このインタラクションが反応するイベント名です。子コンポーネントにこの指定されたイベントのどれかが発生すると、
	 * 仕事の実行を試みます。
	 */
	var _events : Array<String>;
	/** このインタラクションに登録されているアクションです。 */
	var _acts : Array<S -> Void>;
	/** このインタラクションを保持する親UXControllerインスタンスです。 */
	var _ctrl : UXController<S>;
	/** このインタラクションが発生した時に呼び出されるリスナー達です。*/
	var _listener : Hash<S -> Null<UXInteractionParameter> -> Void>;		

	// }}}
	// {{{ public var name(default, null) : String
	/**
	 * このインタラクションを識別できる名前です。
	 */
	public var name(default, null) : String;
	// }}}
	// {{{ public var judge(default, default) : S -> Bool
	/**
	 * このインタラクションで実行される仕事を行ってもいいかどうか判定する関数です。
	 */
	public var judge(default, default) : S -> Bool;
	// }}}
	// {{{ public var work(default, default) : S -> Null<UXInteractionParameter> -> Void
	/**
	 * このインタラクションで実行される仕事です。
	 */
	public var work(default, default) : S -> Null<UXInteractionParameter> -> Void;
	// }}}
	// {{{ public function new()
	/**
	 * コンストラクタです。
	 */
	public function new()
	{
		//just sample
		_events = new Array();
		_acts = new Array();
		_listener = new Hash();

		this.judge = function(s) return true;
		this.work = function(s,p) {};

	}
	// }}}
	// {{{ public function addReactEvent( event : String ) : Void
	/**
	 * このインタラクションを起動するトリガーとなる低レベルイベント(マウスとキーボードのイベント)を指定します。
	 * このインタラクションが作用するオブジェクトに指定されたイベントが発生すると、doWork関数が実行され、judge関数
	 * の判断を経てwork関数が実行されます。
	 */
	public function addReactEvent( event : String ) : Void
	{
		//just sample
		_events.push(event);
	}
	// }}}
	// {{{ public function removeReactEvent( event : String ) : Void
	/**
	 *　このインタラクションを起動するトリガーとなる低レベルイベント(マウスとキーボードのイベント)の登録を解除します。
	 */
	public function removeReactEvent( event : String ) : Void
	{
		//just sample
		_events.remove(event);
	}
	// }}}
	// {{{ public function getEvents() : Array<String>
	/**
	 * 現在の盗賊済みイベントの取得。
	 */
	public function getEvents() : Array<String>
	{
		return _events;
	}
	// }}}
	// {{{ public function addAct( act : S -> Void ) : Void
	/**
	 * このインタラクションが発生した時に発動するアクションを登録できます。登録された順番に実行されます。
	 */
	public function addAct( act : S -> Void ) : Void
	{
		_acts.push(act);		
	}
	// }}}
	// {{{ public function removeAct( act : S -> Void ) : Void
	/**
	 * 登録されているアクションから actを削除します。
	 */
	public function removeAct( act : S -> Void ) : Void
	{
	}
	// }}}
	// {{{ public function ( state : S, param : Null<UXInteractionParameter> ) : Void
	/**
	 * 状態判定を行った上で画面反応や内部状態の変更を行うメソッド。通常は、この関数が親UXControllerの子UXObjectsのリ
	 * スナーに登録され、イベントがした時に呼び出されます。プログラムが直接内部状態の変更を呼び出したい時は、第二引数にAny
	 * を指定して呼び出してください。Anyの場合には登録されたactを実行せずにworkを呼び出します。
	 */
	public function doWork( state : S, param : Null<UXInteractionParameter> ) : Void
	{
		if( judge( state ) ) {
			if( param != null ) {
				switch( param ) {
					case Any( v ) : // Anyの場合は視覚的応答なし
					default :  // 視覚的応答実行
						for( a in _acts.iterator() ) {
							a( state );
						}
				}
				
			}
			work( state, param );
			for( l in _listener.iterator() ) {
				l( state, param ); // オブザーバーの呼び出し
			}
		}
	}
	// }}}
	// {{{ public function addListener( f : S -> Null<UXInteractionParameter> -> Void )
	/**
	 * 名前付きのオブザーバーを登録する関数。指定されたイベントが発生すると、登録された関数は登録された順番に呼ばれます。
	 */
	public function addListener( name : String, f : S -> Null<UXInteractionParameter> -> Void )
	{
		_listener.set( name, f );
	}
	// }}}
	// {{{ public function removeListener( name : String )
	/**
	 * 指定された名前のイベントオブザーバーの登録を解除する関数です。
	 */
 	public function removeListener( name : String  )
	{
		_listener.remove( name );
	}
	// }}}
}
// }}}
